const CacheFactory = require('../../utils/cacheFactory');
const { JJCourse } = require('../../models/ctcdb');
const config = require('../../utils/configUtil').getConfig;
const wx = config.wechat;
const request = require('request');
const oss = require('ali-oss');
const BaseResp = require('../../utils/baseResp');
const errorCode = require('../../utils/errorCode');
let Duplex = require('stream').Duplex;
const store = oss({
  accessKeyId: config.oss.accessKeyId,
  accessKeySecret: config.oss.accessKeySecret,
  bucket: config.oss.bucket,
  region: config.oss.endPoint,
});

async function getAccessToken() {
  const tokenKey = 'wx:access:token:';
  const token = await CacheFactory.getInstance().get(tokenKey);
  if (!token) {
    const { appId, secret } = wx;
    const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appId}&secret=${secret}`;
    return new Promise((resolve, reject) => request({
      method: 'GET',
      uri: url
    }, async (err, response, body) => {
      if (err) {
        return reject(err);
      }
      try {
        body = JSON.parse(body);
        if (body.errcode) {
          return reject(body.errmsg);
        }
        const { access_token } = body;
        await CacheFactory.getInstance().set(tokenKey, body.access_token, 7000); // 避免和微信冲突
        return resolve(access_token);
        // body.access_token;
      } catch (e) {
        return reject(e);
      }
    }));
  }
  return token;
}

async function getShareCode({ courseId, userId, width, page }) {
  const course = await JJCourse.findOne({
    where: {
      id: courseId
    },
    raw: true,
    attributes: ['shareUrl', 'type'],
  });
  if (!course) {
    throw BaseResp.error(errorCode.COURSE.NOT_FOUND)
  }
  if (course.shareUrl) {
    return course.shareUrl;
  }
  const json = {
    scene: courseId,
    width,
  };
  if (page) {
    json.page = page
  }
  const token = await getAccessToken();
  const url = `https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=${token}`;
  return new Promise((resolve, reject) => {
    return request({
      uri: url,
      method: 'POST',
      encoding: null,
      json
    }, async (err, response, body) => {
      if (err) {
        return reject(err);
      }
      const imgBuffer = Buffer.from(body, 'binary');
      try {
        if (body.errcode) {
          return reject(body.errmsg);
        }
        const result = await store.putStream(`share/detail_${courseId}.jpeg`, bufferToStream(imgBuffer));
        let url = result.url;
        url = url.replace(/http/g, 'https');
        await JJCourse.update({
          shareUrl: url
        }, {
          where: {
            id: courseId
          }
        });
        return resolve(url);
      } catch (e) {
        return reject(e);
      }
    })
  })
}

function bufferToStream(buffer) {
  let stream = new Duplex();
  stream.push(buffer);
  stream.push(null);
  return stream;
}
module.exports = {
  getShareCode
};
